/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\
 * This is GNU Go, a Go program. Contact gnugo@gnu.org, or see       *
 * http://www.gnu.org/software/gnugo/ for more information.          *
 *                                                                   *
 * Copyright 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007,   *
 * 2008, 2009, 2010 and 2011 by the Free Software Foundation.        *
 *                                                                   *
 * This program is free software; you can redistribute it and/or     *
 * modify it under the terms of the GNU General Public License as    *
 * published by the Free Software Foundation - version 3 or          *
 * (at your option) any later version.                               *
 *                                                                   *
 * This program is distributed in the hope that it will be useful,   *
 * but WITHOUT ANY WARRANTY; without even the implied warranty of    *
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the     *
 * GNU General Public License in file COPYING for more details.      *
 *                                                                   *
 * You should have received a copy of the GNU General Public         *
 * License along with this program; if not, write to the Free        *
 * Software Foundation, Inc., 51 Franklin Street, Fifth Floor,       *
 * Boston, MA 02111, USA.                                            *
\* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */

#include "gnugo.h"

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>

#include "interface.h"
#include "sgftree.h"
#include "gg_utils.h"
#include "liberty.h"

static void replay_node(SGFNode *node, int color_to_test, float *replay_score,
			float *total_score);


/* --------------------------------------------------------------*/
/* replay a game */
/* --------------------------------------------------------------*/

void
play_replay(SGFTree *tree, int color_to_replay)
{
  char *tmpc = NULL;
  float replay_score = 0.0;
  float total_score = 0.0;

  SGFNode *node = tree->root;

  /* Board size and komi are already set up correctly since the game
   * has already been loaded before this function is called. Now we
   * only have to clear the board before starting over.
   */
  clear_board();
 
  if (!quiet) {
    printf("Board Size:   %d\n", board_size);
    if (sgfGetCharProperty(node, "HA", &tmpc))
      printf("Handicap:     %s\n", tmpc);
    printf("Komi:         %.1f\n", komi);
    if (sgfGetCharProperty(node, "RU", &tmpc))
      printf("Ruleset:      %s\n", tmpc);
    if (sgfGetCharProperty(node, "GN", &tmpc))
      printf("Game Name:    %s\n", tmpc);
    if (sgfGetCharProperty(node, "DT", &tmpc))
      printf("Game Date:    %s\n", tmpc);
    if (sgfGetCharProperty(node, "GC", &tmpc))
      printf("Game Comment: %s\n", tmpc);
    if (sgfGetCharProperty(node, "US", &tmpc))
      printf("Game User:    %s\n", tmpc);
    if (sgfGetCharProperty(node, "PB", &tmpc))
      printf("Black Player: %s\n", tmpc);
    if (sgfGetCharProperty(node, "PW", &tmpc))
      printf("White Player: %s\n", tmpc);
    if (sgfGetCharProperty(node, "RE", &tmpc))
      printf("Result:       %s\n", tmpc);
  }

  /*
   * Now actually run through the file.  This is the interesting part.
   * We need to traverse the SGF tree, and every time we encounter a node
   * we need to check what move GNU Go would make, and see if it is OK. 
   */
  while (node) {
    replay_node(node, color_to_replay, &replay_score, &total_score);
    sgffile_output(tree);
    node = node->child;
  }

  if (!quiet)
    printf("Global score: %.2f / %.2f\n", replay_score, total_score);

  if (showtime) {
    gprintf("SLOWEST MOVE: %d at %1m ", slowest_movenum, slowest_move);
    fprintf(stderr, "(%.2f seconds)\n", slowest_time);
    fprintf(stderr, "AVERAGE TIME: %.2f seconds per move\n",
	    total_time / movenum);
    fprintf(stderr, "TOTAL TIME: %.2f seconds\n",
	    total_time);
  }
}


#define BUFSIZE 128

/*
 * Handle this node.
 */

static void
replay_node(SGFNode *node, int color_to_replay, float *replay_score,
	    float *total_score)
{
  SGFProperty *sgf_prop;  /* iterate over properties of the node */
  SGFProperty *move_prop = NULL; /* remember if we see a move property */
  int color; /* color of move to be made at this node. */
  
  int old_move; /* The move played in the file. */
  int new_move; /* The move generated by GNU Go. */

  char buf[BUFSIZE];

  /* Handle any AB / AW properties, and note presence
   * of move properties.
   */

  for (sgf_prop = node->props; sgf_prop; sgf_prop = sgf_prop->next) {
    switch (sgf_prop->name) {
    case SGFAB:
      /* add black */
      add_stone(get_sgfmove(sgf_prop), BLACK);
      break;
    case SGFAW:
      /* add white */
      add_stone(get_sgfmove(sgf_prop), WHITE);
      break;
    case SGFB:
    case SGFW:
      move_prop = sgf_prop;  /* remember it for later */
      break;
    }
  }

  /* Only generate moves at move nodes. */
  if (!move_prop)
    return;

  old_move = get_sgfmove(move_prop);
  color = (move_prop->name == SGFW) ? WHITE : BLACK;

  if (color == color_to_replay || color_to_replay == GRAY) {
    float new_move_value = 0.0;
    float old_move_value = 0.0;
  
    /* Get a move from the engine for color. */
    int resign;
    new_move = genmove(color, NULL, &resign);
    
    /* Pick up the relevant values from the potential_moves[] array. */
    if (new_move != PASS_MOVE)
      new_move_value = potential_moves[new_move]; 
    if (old_move != PASS_MOVE)
      old_move_value = potential_moves[old_move];
    
    /* Now report on how well the computer generated the move. */
    if (new_move != old_move || !quiet) {
      mprintf("Move %d (%C): ", movenum + 1, color);
    
      if (resign)
	printf("GNU Go resigns ");
      else {
	mprintf("GNU Go plays %1m ", new_move);
	if (new_move != PASS_MOVE)
	  printf("(%.2f) ", new_move_value);
      }
      
      mprintf("- Game move %1m ", old_move);
      if (new_move != PASS_MOVE && old_move_value > 0.0)
	printf("(%.2f) ", old_move_value);
      printf("\n");

      *replay_score += new_move_value - old_move_value;
      *total_score += new_move_value;
    }
    
    if (new_move != old_move) {
      if (resign)
	gg_snprintf(buf, BUFSIZE, "GNU Go resigns - Game move %s (%.2f)",
		    location_to_string(old_move), old_move_value);
      else {      
	gg_snprintf(buf, BUFSIZE,
		    "GNU Go plays %s (%.2f) - Game move %s (%.2f)",
		    location_to_string(new_move), new_move_value,
		    location_to_string(old_move), old_move_value);
	if (new_move != PASS_MOVE)
	  sgfCircle(node, I(new_move), J(new_move));
      }
    }
    else
      gg_snprintf(buf, BUFSIZE, "GNU Go plays the same move %s (%.2f)",
		  location_to_string(new_move), new_move_value);
    
    sgfAddComment(node, buf);
    sgffile_add_debuginfo(node, 0.0);
  }

  /* Finally, do play the move from the file. */
  play_move(old_move, color);
}


/*
 * Local Variables:
 * tab-width: 8
 * c-basic-offset: 2
 * End:
 */
